package com.tianyang.yukuaifuzs.rxservice;

import android.text.TextUtils;
import android.util.Log;

import androidx.core.util.Pair;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.tianyang.yukuaifuzs.common.interfaces.CommonConfig;
import com.tianyang.yukuaifuzs.common.interfaces.UrlConstants;
import com.tianyang.yukuaifuzs.utils.TimeManager;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import rx.Observable;
import rx.functions.Func1;

/**
 * Description：网络接口基类 retrofit2 & RxJava & Http
 * Created by 薛勇军 on 2018/6/14.
 */

public class BaseClient {
    private HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    protected OkHttpClient client;
    private Interceptor headInterceptor;

    protected BaseClient() {
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        headInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request()
                        .newBuilder()
                        .addHeader("timestamp", String.valueOf(TimeManager.getInstance().getCurTimeMillis()))
                        .addHeader("Content-Type", "application/json;charset=UTF-8")
                        .build();
                return chain.proceed(request);
            }
        };

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(UrlConstants.HTTP_TIMEOUT, TimeUnit.SECONDS);//连接超时时间        builder.writeTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//写操作 超时时间
        builder.readTimeout(UrlConstants.HTTP_TIMEOUT, TimeUnit.SECONDS);//读操作超时时间
        // 添加公共参数拦截器
        builder.addInterceptor(logging);
        builder.addInterceptor(headInterceptor);
        builder.sslSocketFactory(SSLSocketClient.getSSLSocketFactory());
        builder.hostnameVerifier(SSLSocketClient.getHostnameVerifier());

        client = builder.build();
    }

    /**
     * response处理
     *
     * @param observable 对象
     */
    public Observable<Pair<MetaBean, JSONObject>> callMap(Observable<Object> observable) {
        return observable.map(new Func1<Object, Pair<MetaBean, JSONObject>>() {
            @Override
            public Pair<MetaBean, JSONObject> call(Object result) {
                if (result == null || TextUtils.isEmpty(result.toString())) {
                    return null;
                }
                Log.e("response处理", JSON.toJSONString(result));
                MetaBean metaBean = JSON.parseObject(JSON.toJSONString(result), MetaBean.class);
                if (metaBean != null && TextUtils.equals(CommonConfig.RET_OK, String.valueOf(metaBean.getCode()))) {
                    if (metaBean.getData() != null) {
                        try {
                            if (!(metaBean.getData() instanceof JSONObject)) {
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("data", metaBean.getData());
                                return new Pair<>(metaBean, jsonObject);
                            }
                            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(metaBean.getData()));
                            return new Pair<>(metaBean, jsonObject);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return new Pair<>(metaBean, null);
                    }
                }
                return new Pair<>(metaBean, null);
            }
        });
    }

    /**
     * list response处理
     *
     * @param observable 对象
     */
    public Observable<Pair<MetaBean, Object>> callMapList(Observable<Object> observable) {
        return observable.map(new Func1<Object, Pair<MetaBean, Object>>() {
            @Override
            public Pair<MetaBean, Object> call(Object result) {
                if (result == null || TextUtils.isEmpty(result.toString())) {
                    return null;
                }
                Log.e("response处理", JSON.toJSONString(result));
                MetaBean metaBean = JSON.parseObject(JSON.toJSONString(result), MetaBean.class);
                if (metaBean != null && TextUtils.equals(CommonConfig.RET_OK, String.valueOf(metaBean.getCode()))) {
                    if (metaBean.getData() != null) {
                        try {
                            if (metaBean.getData() instanceof JSONArray) {
                                return new Pair<>(metaBean, metaBean.getData());
                            }
                            Map<String, Object> mapData = JSON.parseObject(JSON.toJSONString(metaBean.getData()), new TypeReference<Map<String, Object>>(){});
                            if (mapData != null &&mapData.containsKey("list")) {
                                return new Pair<>(metaBean, mapData.get("list"));
                            } else {
                                return new Pair<>(metaBean, metaBean.getData());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return new Pair<>(metaBean, null);
                    }
                }
                return new Pair<>(metaBean, null);
            }
        });
    }

    /**
     * 创建Obserable
     */
    public <T> Observable<T> toObservable(Pair<MetaBean, T> pair) {
        if (pair == null || pair.first == null || TextUtils.isEmpty(String.valueOf(pair.first.getCode()))) {
            return Observable.error(RxError.create(RxError.ERROR_UNKNOWN, RxError.ERROR_UNKNOWN));
        }
        if (TextUtils.equals(CommonConfig.RET_OK, String.valueOf(pair.first.getCode()))) {
            return Observable.just(pair.second);
        }
        String message = pair.first.getMessage();
        if (TextUtils.isEmpty(message) && pair.first.getData() != null) {
            message = pair.first.getData().toString();
        }
        if (TextUtils.equals(CommonConfig.OFFLINE, String.valueOf(pair.first.getCode()))) {
            return Observable.error(RxError.create(RxError.ERROR_OFFLINE, String.valueOf(pair.first.getCode()), message));
        }
        return Observable.error(RxError.create(RxError.ERROR_TYPE_DATA, String.valueOf(pair.first.getCode()), message));
    }
}
